package com.atguigu.mvc.handler;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletContext;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

@Controller
public class UploadHandler {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ServletContext servletContext;

    @RequestMapping("/save/head/picture")
    public String saveHeadPictureForTransfer(
            @RequestParam("headPicture") MultipartFile headPicture,

            Model model
    ) throws IOException {

        // 由于虚拟路径在 Web 应用结构不变的前提下永远不变，所以可以在代码中写死
        // 后面再借助 servletContext 对象转换为适合当前服务器的真实物理路径，就能够保证当前程序跨平台运行
        // 跨平台：既能在本地运行，又能在部署到服务器后正常运行
        // 虚拟路径的概念：
        // 在Windows系统的真实物理路径
        // D:/idea-workspace/atguigu-maven-210422-new/pro31-springmvc-upload/src/main/webapp/upload/a.txt
        // 通过 Tomcat 访问文件的路径就是虚拟路径
        // http://localhost:8080/demo/upload/a.txt
        // 指定保存文件的目录的虚拟路径
        String targetFolderVirtualPath = "/upload";

        // 将目录的虚拟路径根据当前实际服务器情况动态转换为真实物理路径，作为文件最终保存的目录
        String targetFolderRealPath = servletContext.getRealPath(targetFolderVirtualPath);

        logger.debug("真实物理路径 = " + targetFolderRealPath);

        // 文件最终保存的名称（主体文件名.扩展名）
        // 生成主体文件名
        String fileNameMainPart = UUID.randomUUID().toString().replace("-", "").toUpperCase();

        // 从文件的原始名称中截取出扩展名
        // 获取原始文件名
        String originalFilename = headPicture.getOriginalFilename();

        // 截取扩展名
        String fileNameExtPart = originalFilename.substring(originalFilename.lastIndexOf("."));

        // 拼接文件名
        String fileName = fileNameMainPart + fileNameExtPart;

        // 拼接文件最终保存的路径，注意目录和文件名之间要加“/”
        // aaa
        // bbb.jpg
        // aaa/bbb.jpg
        String fileSavePath = targetFolderRealPath + "/" + fileName;

        // 创建 File 对象，对应文件即将要保存到的目标位置
        File dest = new File(fileSavePath);

        // 执行转存
        headPicture.transferTo(dest);

        // 拼接一个页面上可以访问的路径
        String fileVirtualPath = targetFolderVirtualPath + "/" + fileName;

        // 将文件访问路径存入模型
        model.addAttribute("filePath", fileVirtualPath);

        return "target";
    }

    public static void main(String[] args) {
        String originalFilename = "aaa.jpg";
        String fileNameExtPart = originalFilename.substring(originalFilename.lastIndexOf("."));
        System.out.println("fileNameExtPart = " + fileNameExtPart);
    }

    // @RequestMapping("/save/head/picture")
    public String saveHeadPicture(
            @RequestParam("nickName") String nickName,

            // MultipartFile 是专门接收上传文件的类型
            // 浏览器端的表单用一个名字携带一个文件：使用单个 MultipartFile 类型变量接收
            // 浏览器端的表单用一个名字携带多个文件：使用 List<MultipartFile> 类型变量接收
            @RequestParam("headPicture") MultipartFile headPicture,

            // 如果有另外一个名字携带了另外一个文件，那就用另外一个 MultipartFile 接收
            @RequestParam("backgroundPicture") MultipartFile backgroundPicture
            ) throws IOException {

        logger.debug("[普通表单项] nickName = " + nickName);
        logger.debug("[文件表单项] 请求参数名 = " + headPicture.getName());
        logger.debug("[文件表单项] 原始文件名 = " + headPicture.getOriginalFilename());
        logger.debug("[文件表单项] 判断当前上传文件是否为空 = " + (headPicture.isEmpty()?"空":"非空"));
        logger.debug("[文件表单项] 当前上传文件的大小 = " + headPicture.getSize());
        logger.debug("[文件表单项] 当前上传文件的二进制内容组成的字节数组 = " + headPicture.getBytes());
        logger.debug("[文件表单项] 能够读取当前上传文件的输入流 = " + headPicture.getInputStream());

        logger.debug("[另一个文件] 原始文件名 = " + backgroundPicture.getOriginalFilename());
        return "target";
    }

    @RequestMapping("/save/multi/file")
    public String saveMultiFile(
            @RequestParam("fileList") List<MultipartFile> fileList) {

        for (MultipartFile multipartFile : fileList) {
            String originalFilename = multipartFile.getOriginalFilename();
            logger.debug("originalFilename = " + originalFilename);
        }

        return "target";
    }

}
